use std::time::{Duration, Instant};
use std::sync::Arc;
use tokio::sync::Mutex;

/// 进度条显示
pub struct ProgressBar {
    total: u64,
    current: u64,
    start_time: Instant,
    last_update: Instant,
    width: usize,
    show_speed: bool,
    show_eta: bool,
}

impl ProgressBar {
    pub fn new(total: u64) -> Self {
        Self {
            total,
            current: 0,
            start_time: Instant::now(),
            last_update: Instant::now(),
            width: 50,
            show_speed: true,
            show_eta: true,
        }
    }

    pub fn with_width(mut self, width: usize) -> Self {
        self.width = width;
        self
    }

    pub fn with_speed(mut self, show_speed: bool) -> Self {
        self.show_speed = show_speed;
        self
    }

    pub fn with_eta(mut self, show_eta: bool) -> Self {
        self.show_eta = show_eta;
        self
    }

    pub fn update(&mut self, current: u64) {
        self.current = current;
        self.last_update = Instant::now();
    }

    pub fn display(&self) -> String {
        let percentage = if self.total > 0 {
            (self.current as f64 / self.total as f64) * 100.0
        } else {
            0.0
        };

        let filled = (percentage / 100.0 * self.width as f64) as usize;
        let bar = "█".repeat(filled) + &"░".repeat(self.width - filled);

        let mut result = format!(
            "\r[{}] {:.1}% ({}/{})",
            bar, percentage, self.current, self.total
        );

        if self.show_speed {
            let elapsed = self.start_time.elapsed().as_secs_f64();
            if elapsed > 0.0 {
                let speed = self.current as f64 / elapsed;
                result.push_str(&format!(" {:.2} KB/s", speed / 1024.0));
            }
        }

        if self.show_eta && self.current > 0 && self.current < self.total {
            let elapsed = self.start_time.elapsed().as_secs_f64();
            let remaining_bytes = self.total - self.current;
            let speed = self.current as f64 / elapsed;
            if speed > 0.0 {
                let eta_seconds = remaining_bytes as f64 / speed;
                result.push_str(&format!(" ETA: {:.0}s", eta_seconds));
            }
        }

        result
    }

    pub fn finish(&self) -> String {
        let duration = self.start_time.elapsed();
        let speed = if duration.as_secs_f64() > 0.0 {
            self.total as f64 / duration.as_secs_f64()
        } else {
            0.0
        };

        format!(
            "\n✅ Completed: {} bytes in {:.2}s ({:.2} KB/s)",
            self.total,
            duration.as_secs_f64(),
            speed / 1024.0
        )
    }
}

/// 传输进度跟踪器
pub struct TransferProgress {
    pub id: u64,
    pub filename: String,
    pub total_size: Option<u64>,
    pub transferred: u64,
    pub speed: f64,
    pub start_time: Instant,
    pub status: TransferStatus,
    pub error: Option<String>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TransferStatus {
    Pending,
    Running,
    Completed,
    Failed,
    Cancelled,
}

impl TransferProgress {
    pub fn new(id: u64, filename: String, total_size: Option<u64>) -> Self {
        Self {
            id,
            filename,
            total_size,
            transferred: 0,
            speed: 0.0,
            start_time: Instant::now(),
            status: TransferStatus::Pending,
            error: None,
        }
    }

    pub fn update(&mut self, transferred: u64) {
        self.transferred = transferred;
        let elapsed = self.start_time.elapsed().as_secs_f64();
        if elapsed > 0.0 {
            self.speed = transferred as f64 / elapsed;
        }
    }

    pub fn set_status(&mut self, status: TransferStatus) {
        self.status = status;
    }

    pub fn set_error(&mut self, error: String) {
        self.error = Some(error);
        self.status = TransferStatus::Failed;
    }

    pub fn progress_percentage(&self) -> f64 {
        if let Some(total) = self.total_size {
            if total > 0 {
                (self.transferred as f64 / total as f64) * 100.0
            } else {
                0.0
            }
        } else {
            0.0
        }
    }

    pub fn format_progress(&self) -> String {
        let status_icon = match self.status {
            TransferStatus::Pending => "⏳",
            TransferStatus::Running => "🔄",
            TransferStatus::Completed => "✅",
            TransferStatus::Failed => "❌",
            TransferStatus::Cancelled => "🚫",
        };

        let progress_bar = if let Some(total) = self.total_size {
            let percentage = self.progress_percentage();
            let filled = (percentage / 100.0 * 20.0) as usize;
            let bar = "█".repeat(filled) + &"░".repeat(20 - filled);
            format!("[{}] {:.1}%", bar, percentage)
        } else {
            format!("[{}] {} bytes", "░".repeat(20), self.transferred)
        };

        let mut result = format!(
            "{} {} {} ({}/{})",
            status_icon,
            self.filename,
            progress_bar,
            self.transferred,
            self.total_size.map_or("?".to_string(), |s| s.to_string())
        );

        if self.speed > 0.0 {
            result.push_str(&format!(" {:.2} KB/s", self.speed / 1024.0));
        }

        if let Some(ref error) = self.error {
            result.push_str(&format!(" Error: {}", error));
        }

        result
    }
}

/// 多传输进度显示器
pub struct MultiTransferDisplay {
    transfers: Arc<Mutex<Vec<TransferProgress>>>,
    last_update: Instant,
    update_interval: Duration,
}

impl MultiTransferDisplay {
    pub fn new() -> Self {
        Self {
            transfers: Arc::new(Mutex::new(Vec::new())),
            last_update: Instant::now(),
            update_interval: Duration::from_millis(500),
        }
    }

    pub async fn add_transfer(&self, id: u64, filename: String, total_size: Option<u64>) {
        let mut transfers = self.transfers.lock().await;
        transfers.push(TransferProgress::new(id, filename, total_size));
    }

    pub async fn update_transfer(&self, id: u64, transferred: u64) {
        let mut transfers = self.transfers.lock().await;
        if let Some(transfer) = transfers.iter_mut().find(|t| t.id == id) {
            transfer.update(transferred);
        }
    }

    pub async fn set_transfer_status(&self, id: u64, status: TransferStatus) {
        let mut transfers = self.transfers.lock().await;
        if let Some(transfer) = transfers.iter_mut().find(|t| t.id == id) {
            transfer.set_status(status);
        }
    }

    pub async fn set_transfer_error(&self, id: u64, error: String) {
        let mut transfers = self.transfers.lock().await;
        if let Some(transfer) = transfers.iter_mut().find(|t| t.id == id) {
            transfer.set_error(error);
        }
    }

    pub async fn display(&self) -> String {
        let transfers = self.transfers.lock().await;
        let mut result = String::new();

        result.push_str("\n📊 Transfer Progress:\n");
        result.push_str("====================\n");

        for transfer in transfers.iter() {
            result.push_str(&transfer.format_progress());
            result.push('\n');
        }

        result
    }

    pub async fn should_update(&mut self) -> bool {
        if self.last_update.elapsed() >= self.update_interval {
            self.last_update = Instant::now();
            true
        } else {
            false
        }
    }

    pub async fn get_transfer_count(&self) -> usize {
        let transfers = self.transfers.lock().await;
        transfers.len()
    }

    pub async fn get_completed_count(&self) -> usize {
        let transfers = self.transfers.lock().await;
        transfers.iter().filter(|t| matches!(t.status, TransferStatus::Completed)).count()
    }

    pub async fn get_failed_count(&self) -> usize {
        let transfers = self.transfers.lock().await;
        transfers.iter().filter(|t| matches!(t.status, TransferStatus::Failed)).count()
    }
}
